<?php
/**
 * 유틸리티 - 문자열
 *
 * <code>
 * $utilString = utilString::getInstance();
 * // UTF 호환 문자열 자르기
 * // 결과 : 가나다라A
 * $utilString->cutString('가나다라ABCDEF', 10);
 * // HTML Decode
 * // 결과 : <script type=\'text/javascript\' src="./example.js" />
 * $utilString->htmlDecode('&lt;script type=&#039;text/javascript&#039; src=&quot;./example.js&quot; /&gt;');
 * // HTML Encode
 * // 결과 : &lt;script type=&#039;text/javascript&#039; src=&quot;./example.js&quot; /&gt;
 * $utilString->htmlEncode('<script type=\'text/javascript\' src="./example.js" />');
 * // 슬래쉬(\) 제거
 * // 결과 : I\'m Sorry', 'That\'s all right.
 * $utilString->stripSlashes('I\\\'m Sorry', 'That\\\'s all right.');
 * // HTML 태그 제거
 * // 결과 : Test
 * $utilString->stripTags('<html><body><div><a />Test</body></html>');
 * </code>
 *
 * @package    util
 *
 * @version 1.0
 * @author    jylee3@simplexi.com
 */
class utilString
{
    /**
     * utilSting Instance
     *
     * <code>
     * $utilSting = utilString::getInstance();
     * </code>
     *
     * @return    utilString
     */
    public static function getInstance()
    {
        return utilSplClass::load('utilString');
    }

    /**
     * 문자열 길이 반환
     * (멀티바이트 문자열 지원)
     *
     * @param string $sStr
     * @return int
     */
    private static function strlen($sStr)
    {
        $limit = 0;
        $count = 0;
        $byte_len = strlen($sStr);
        $isCompleteChar = FW_BYTE_PER_CHAR;

        for ($i = 0; $i < $byte_len; ++$i) {
            if ( ord($sStr[$i]) >= 0x80 ) {

                ++$count;

                if ( $count == $isCompleteChar ) {
                    ++$limit;
                    $count = 0;
                }

            } else {

                ++$limit;

            }
        }

        return $limit;
    }

    /**
     * 문자열 컷팅
     * (멀티바이트 문자열 지원)
     *
     * <code>
     * // 결과 : 가나다라
     * $utilString->cutString('가나다라ABCDEF', 4);
     * </code>
     *
     * @param string $sStr     문자열
     * @param int $iLen     길이
     * @param string $sSuffix  추가 문자열
     *
     * @return String    결과 문자열
     */
    public function cutString($sStr, $iLen=0, $sSuffix='')
    {
        if ( $iLen == 0 ) return $sStr;
        if ( self::strlen($sStr) < $iLen ) return $sStr;

        $limit = 0;
        $count = 0;
        $byte_len = strlen($sStr);
        $isCompleteChar = FW_BYTE_PER_CHAR;

        for ($i = 0; $i < $byte_len; ++$i) {
            if ( ord($sStr[$i]) >= 0x80 ) {

                ++$count;

                if ( $count == $isCompleteChar ) {
                    ++$limit;
                    $count = 0;
                }

            } else {

                ++$limit;

            }

            if ( $limit == $iLen ) {
                $limit = $i + 1;
                break;
            }
        }

        $result = substr($sStr, 0, $limit);

        return (strlen($result) < $byte_len) ? $result.$sSuffix : $result;
    }

    /**
     * 해당하는 HTML 엔티티를 문자로 변환
     *
     * <code>
     * // 결과 : <script type=\'text/javascript\' src="./example.js" />
     * $utilString->htmlDecode('&lt;script type=&#039;text/javascript&#039; src=&quot;./example.js&quot; /&gt;');
     * </code>
     *
     * @param String $sHtml    HTML 데이터
     *
     * @return String    결과 문자열
     */
    public function htmlDecode($sHtml)
    {
        return strtr($sHtml, array('&amp;' => '&', '&quot;' => '"', '&#039;' => "'", '&lt;' => '<', '&gt;' => '>'));
    }

    /**
     * 문자열에서 해당하는 문자를 HTML 엔티티로 변환
     *
     * <code>
     * // 결과 : &lt;script type=&#039;text/javascript&#039; src=&quot;./example.js&quot; /&gt;
     * $utilString->htmlEncode('<script type=\'text/javascript\' src="./example.js" />');
     * </code>
     *
     * @param String $sString    문자열
     *
     * @return String    결과 문자열
     */
    public function htmlEncode($sString)
    {
        return strtr($sString, array('&' => '&amp;', '"' => '&quot;', "'" => '&#039;', '<' => '&lt;', '>' => '&gt;'));
    }

    /**
     * 다차원 배열의 문자열 또는 문자열에서 백슬래쉬를 제거
     *
     * <code>
     * // 결과 : I\'m Sorry', 'That\'s all right.
     * $utilString->stripSlashes('I\\\'m Sorry', 'That\\\'s all right.');
     * </code>
     *
     * @param Array|String $mString    백슬래쉬를 제거할 문자열 또는 배열
     *
     * @return Array|String
     */
    public function stripSlashes(&$mString)
    {
        return is_array($mString)? array_map(array(&$this, 'stripSlashes'), $mString) : stripslashes($mString);
    }

    /**
     * 태그를 제거한 후 반환합니다.
     *
     * 참고 : 이 기능은 완성되지 않은 태그를 포함한 모든 태그를 제거합니다.
     *
     * <code>
     * // 결과 : Test
     * $utilString->stripTags('<html><body><div><a />Test</body></html>');
     * </cdoe>
     *
     * @param String $sHtmlDocument    태그를 포함한 HTML 문서
     *
     * @return String    결과 문자열
     */
    public function stripTags($sHtmlDocument)
    {
        $aRemoveTag = array('@<script[^>]*?\>.*?<\/script>@si',   // Strip out javascript
                            '@<[\/\!]*?[^<>]*?\>@si',            // Strip out HTML tags
                            '@<style[^>]*?\>.*?<\/style>@siU',    // Strip style tags properly
                            '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments including CDATA
        );

        return preg_replace($aRemoveTag, '', $sHtmlDocument);
    }
}
